/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package servlets;

import connection.DBConnection;
import dto.CommentDetail;
import dto.Comments;
import org.ocpsoft.prettytime.PrettyTime;
import org.xml.sax.SAXException;

import java.io.*;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.xml.XMLConstants;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import javax.xml.validation.Schema;
import javax.xml.validation.SchemaFactory;

/**
 * @author Tung An
 */
@WebServlet(name = "CommentServlet", urlPatterns = {"/CommentServlet"})
public class CommentServlet extends HttpServlet {
    private PrettyTime prettyTime = new PrettyTime();

    /**
     * Processes requests for both HTTP
     * <code>GET</code> and
     * <code>POST</code> methods.
     *
     * @param request  servlet request
     * @param response servlet response
     * @throws javax.servlet.ServletException if a servlet-specific error occurs
     * @throws java.io.IOException            if an I/O error occurs
     */
    protected void processRequest(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        response.setContentType("text/plain");
        response.setCharacterEncoding("UTF-8");
        PrintWriter out = response.getWriter();
        String param = request.getParameter("action");
        try {
            if (param != null) {
                if (param.equalsIgnoreCase("newComment")) {
                    CommentDetail comment = this.createCommentObj(request.getParameter("xml"));
                    Integer commentId = this.insertComment(comment);
                    out.print("<commentid>" + commentId + "</commentid>");
                } else if (param.equalsIgnoreCase("getComment")) {
                    Integer lookId = Integer.parseInt(request.getParameter("lookId"));
                    out.write(this.getComments(lookId));
                } else if (param.equalsIgnoreCase("deleteComment")) {
                    Integer commentId = Integer.parseInt(request.getParameter("commentId"));
                    out.write("<result>" + this.deleteComment(commentId) + "</result>");
                }
            }
        } finally {
            out.close();
        }
    }

    private String getComments(Integer lookId) {
        StringWriter xmlWriter = new StringWriter();
        DBConnection con = new DBConnection("localhost", "root", "123456", "xml");
        try {
            String query = "SELECT * FROM comments, users WHERE comments.userID = users.userID AND comments.lookID=?";
            PreparedStatement st = con.prepareStatement(query);
            st.setInt(1, lookId);
            ResultSet rs = st.executeQuery();
            Comments comments = new Comments();
            List<CommentDetail> commentList = new ArrayList<CommentDetail>();
            while (rs.next()) {
                CommentDetail comment = new CommentDetail();
                comment.setLookid(rs.getShort("lookID"));
                comment.setUsername(rs.getString("username"));
                comment.setUpdatetime(prettyTime.format(rs.getTimestamp("updateTime")));
                comment.setCommentid(rs.getShort("id"));
                comment.setUserid(rs.getShort("userID"));
                String avatarURL = "";
                if (rs.getString("avatarURL") != null) {
                    avatarURL = rs.getString("avatarURL");
                }
                comment.setAvatarurl(avatarURL);
                comment.setContent(rs.getString("content"));
                commentList.add(comment);
            }
            comments.setComment(commentList);
            try {
                JAXBContext ctx = JAXBContext.newInstance(Comments.class);
                Marshaller mar = ctx.createMarshaller();

                SchemaFactory sf = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
                Schema schema = sf.newSchema(new File("/XML/schemas/comments.xsd"));
                mar.setSchema(schema);
                mar.setProperty(Marshaller.JAXB_ENCODING, "UTF-8");
                mar.marshal(comments, xmlWriter);
            } catch (JAXBException ex) {
                Logger.getLogger(ProcessServlet.class.getName()).log(Level.SEVERE, null, ex);
            } catch (SAXException e) {
                e.printStackTrace();
            }

        } catch (SQLException ex) {
            Logger.getLogger(ProcessServlet.class.getName()).log(Level.SEVERE, null, ex);
        }
        con.close();
        return xmlWriter.toString();
    }

    private CommentDetail createCommentObj(String xml) {
        if (xml.isEmpty()) {
            return null;
        }
        try {
            JAXBContext context = JAXBContext.newInstance(Comments.class);
            Unmarshaller unmarshaller = context.createUnmarshaller();
            InputStream stream = new ByteArrayInputStream(xml.getBytes());
            Comments comments = (Comments) unmarshaller.unmarshal(stream);
            return comments.getComment().get(0);
        } catch (JAXBException e) {
            e.printStackTrace();
        }
        return null;
    }

    private int insertComment(CommentDetail comment) {
        try {
            DBConnection con = new DBConnection("localhost", "root", "123456", "xml");
            String update = "UPDATE comments SET content = ?, updateTime = now(), lookID = ?, userId = ? WHERE id=?";
            String query = "INSERT INTO comments (content, updateTime, lookID, userId) VALUES (?,now(),?,?)";
            PreparedStatement st;
            if (comment.getCommentid() != 0) {
                st = con.prepareStatement(update);
                st.setInt(4, comment.getCommentid());
            } else {
                st = con.prepareStatement(query, true);
            }

            st.setString(1, comment.getContent());
            st.setInt(2, comment.getLookid());
            st.setInt(3, comment.getUserid());
            st.executeUpdate();
            if (comment.getCommentid() == 0) {
                ResultSet rs = st.getGeneratedKeys();
                if (rs != null && rs.next()) {
                    return rs.getShort(1);
                }
            }
            con.close();
        } catch (SQLException ex) {
            Logger.getLogger(ProcessServlet.class.getName()).log(Level.SEVERE, null, ex);
        }
        return 0;
    }

    private Boolean deleteComment(Integer commentId) {
        DBConnection con = new DBConnection("localhost", "root", "123456", "xml");
        try {
            String query = "DELETE FROM comments WHERE id=?";
            PreparedStatement st = con.prepareStatement(query);
            st.setInt(1, commentId);
            st.executeUpdate();
            return true;
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return false;
    }

    // <editor-fold defaultstate="collapsed" desc="HttpServlet methods. Click on the + sign on the left to edit the code.">

    /**
     * Handles the HTTP
     * <code>GET</code> method.
     *
     * @param request  servlet request
     * @param response servlet response
     * @throws javax.servlet.ServletException if a servlet-specific error occurs
     * @throws java.io.IOException            if an I/O error occurs
     */
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        processRequest(request, response);
    }

    /**
     * Handles the HTTP
     * <code>POST</code> method.
     *
     * @param request  servlet request
     * @param response servlet response
     * @throws javax.servlet.ServletException if a servlet-specific error occurs
     * @throws java.io.IOException            if an I/O error occurs
     */
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        processRequest(request, response);
    }

    /**
     * Returns a short description of the servlet.
     *
     * @return a String containing servlet description
     */
    @Override
    public String getServletInfo() {
        return "Short description";
    }// </editor-fold>
}
